package com.fsnbigdata.service.impl;
import com.fsnbigdata.domain.*;
import com.fsnbigdata.domain.dto.NamingPair2;
import com.fsnbigdata.repository.OrganismImageRepository;
import com.fsnbigdata.repository.PlantingImageRepository;
import com.fsnbigdata.repository.PlantingRepository;
import com.fsnbigdata.service.api.PlantConservationService;
import com.fsnbigdata.util.ObjectNull;
import com.fsnbigdata.vo.NewClass;
import com.querydsl.core.types.Predicate;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.roo.addon.layers.service.annotations.RooServiceImpl;
import com.fsnbigdata.repository.PlantConservationRepository;
import com.fsnbigdata.service.api.IntroductionService;
import com.fsnbigdata.service.api.PhenologyRecordService;
import com.fsnbigdata.service.api.PlantingService;
import com.fsnbigdata.service.api.PropagationCultivationService;
import io.springlets.data.domain.GlobalSearch;

import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

/**
 * = PlantConservationServiceImpl
 *
 * TODO Auto-generated class documentation
 *
 */
@RooServiceImpl(service = PlantConservationService.class)
@Service
@Transactional(readOnly = true)
public class PlantConservationServiceImpl implements PlantConservationService {

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    private PlantConservationRepository plantConservationRepository;

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    @Autowired
    private PlantingRepository plantingRepository;

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    @Autowired
    private PlantingImageRepository PlantingImageRepository;

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    private PropagationCultivationService propagationCultivationService;

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    private IntroductionService introductionService;

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    private PlantingService plantingService;

    /**
     * TODO Auto-generated attribute documentation
     *
     */
    private PhenologyRecordService phenologyRecordService;

    /**
     * TODO Auto-generated constructor documentation
     *
     * @param plantConservationRepository
     * @param introductionService
     * @param phenologyRecordService
     * @param plantingService
     * @param propagationCultivationService
     */
    @Autowired
    public PlantConservationServiceImpl(PlantConservationRepository plantConservationRepository, @Lazy IntroductionService introductionService, @Lazy PhenologyRecordService phenologyRecordService, @Lazy PlantingService plantingService, @Lazy PropagationCultivationService propagationCultivationService) {
        setPlantConservationRepository(plantConservationRepository);
        setIntroductionService(introductionService);
        setPhenologyRecordService(phenologyRecordService);
        setPlantingService(plantingService);
        setPropagationCultivationService(propagationCultivationService);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return PlantConservationRepository
     */
    public PlantConservationRepository getPlantConservationRepository() {
        return plantConservationRepository;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservationRepository
     */
    public void setPlantConservationRepository(PlantConservationRepository plantConservationRepository) {
        this.plantConservationRepository = plantConservationRepository;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return IntroductionService
     */
    public IntroductionService getIntroductionService() {
        return introductionService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param introductionService
     */
    public void setIntroductionService(IntroductionService introductionService) {
        this.introductionService = introductionService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return PhenologyRecordService
     */
    public PhenologyRecordService getPhenologyRecordService() {
        return phenologyRecordService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param phenologyRecordService
     */
    public void setPhenologyRecordService(PhenologyRecordService phenologyRecordService) {
        this.phenologyRecordService = phenologyRecordService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return PlantingService
     */
    public PlantingService getPlantingService() {
        return plantingService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantingService
     */
    public void setPlantingService(PlantingService plantingService) {
        this.plantingService = plantingService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return PropagationCultivationService
     */
    public PropagationCultivationService getPropagationCultivationService() {
        return propagationCultivationService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param propagationCultivationService
     */
    public void setPropagationCultivationService(PropagationCultivationService propagationCultivationService) {
        this.propagationCultivationService = propagationCultivationService;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservation
     * @param introductionToAdd
     * @return PlantConservation
     */
    @Transactional
    public PlantConservation addToIntroduction(PlantConservation plantConservation, Iterable<Introduction> introductionToAdd) {
        plantConservation.addToIntroduction(introductionToAdd);
        return getPlantConservationRepository().save(plantConservation);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservation
     * @param phenologyRecordsToAdd
     * @return PlantConservation
     */
    @Transactional
    public PlantConservation addToPhenologyRecords(PlantConservation plantConservation, Iterable<PhenologyRecord> phenologyRecordsToAdd) {
        plantConservation.addToPhenologyRecords(phenologyRecordsToAdd);
        return getPlantConservationRepository().save(plantConservation);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservation
     * @param plantingToAdd
     * @return PlantConservation
     */
    @Transactional
    public PlantConservation addToPlanting(PlantConservation plantConservation, Iterable<Planting> plantingToAdd) {
        plantConservation.addToPlanting(plantingToAdd);
        return getPlantConservationRepository().save(plantConservation);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservation
     * @param propagationCultivationToAdd
     * @return PlantConservation
     */
    @Transactional
    public PlantConservation addToPropagationCultivation(PlantConservation plantConservation, Iterable<PropagationCultivation> propagationCultivationToAdd) {
        plantConservation.addToPropagationCultivation(propagationCultivationToAdd);
        return getPlantConservationRepository().save(plantConservation);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservation
     * @param introductionToRemove
     * @return PlantConservation
     */
    @Transactional
    public PlantConservation removeFromIntroduction(PlantConservation plantConservation, Iterable<Long> introductionToRemove) {
        List<Introduction> introduction = getIntroductionService().findAll(introductionToRemove);
        plantConservation.removeFromIntroduction(introduction);
        return getPlantConservationRepository().save(plantConservation);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservation
     * @param phenologyRecordsToRemove
     * @return PlantConservation
     */
    @Transactional
    public PlantConservation removeFromPhenologyRecords(PlantConservation plantConservation, Iterable<Long> phenologyRecordsToRemove) {
        List<PhenologyRecord> phenologyRecords = getPhenologyRecordService().findAll(phenologyRecordsToRemove);
        plantConservation.removeFromPhenologyRecords(phenologyRecords);
        return getPlantConservationRepository().save(plantConservation);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservation
     * @param plantingToRemove
     * @return PlantConservation
     */
    @Transactional
    public PlantConservation removeFromPlanting(PlantConservation plantConservation, Iterable<Long> plantingToRemove) {
        List<Planting> planting = getPlantingService().findAll(plantingToRemove);
        plantConservation.removeFromPlanting(planting);
        return getPlantConservationRepository().save(plantConservation);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservation
     * @param propagationCultivationToRemove
     * @return PlantConservation
     */
    @Transactional
    public PlantConservation removeFromPropagationCultivation(PlantConservation plantConservation, Iterable<Long> propagationCultivationToRemove) {
        List<PropagationCultivation> propagationCultivation = getPropagationCultivationService().findAll(propagationCultivationToRemove);
        plantConservation.removeFromPropagationCultivation(propagationCultivation);
        return getPlantConservationRepository().save(plantConservation);
    }

    @Override
    public List<NamingPair2> findAllByInitial(String initial) {
        return getPlantConservationRepository().findAllByInitial(initial);
    }

    @Override
    public List getPageList(String name, String latin, Pageable pageable1) {
        List list = new ArrayList(  );
        list.add( plantConservationRepository.queryCountByKey( name,latin ) );
        List<NewClass> plant = new ArrayList <>(  );
        for(Object o:plantConservationRepository.queryAllByKey( name,latin,pageable1 )){
            Object[] objects = (Object[]) o;
            NewClass newClass = new NewClass();
            newClass.setId( ""+objects[0] );
            newClass.setName(ObjectNull.takeOutNull(objects[1]) );
            newClass.setLatin_name( ObjectNull.takeOutNull(objects[2]) );
            newClass.setCreator( ObjectNull.takeOutNull(objects[3] ));
            newClass.setInitial( ObjectNull.takeOutNull(objects[4]) );
            newClass.setFamily(ObjectNull.takeOutNull(objects[5]));
            newClass.setGenus(ObjectNull.takeOutNull(objects[6]));
            newClass.setSpecies(ObjectNull.takeOutNull(objects[7]));
            List<Object> location = plantingRepository.getLocation( ""+objects[0] );
            if(location.size()>0){
                newClass.setLocation( ((Object[])location.get( 0 ))[1]+"" );
                List<String> url = PlantingImageRepository.getUrl( ((Object[])location.get( 0 ))[0]+"" );
                newClass.setUrl( url.size()>0?url.get( 0 ):null );
            }
            newClass.setNumber( ""+objects[0] );
            plant.add( newClass );
        }
        list.add( plant );
        return list;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param plantConservation
     */
    @Transactional
    public void delete(PlantConservation plantConservation) {
        // Clear bidirectional one-to-many parent relationship with Introduction
        for (Introduction item : plantConservation.getIntroduction()) {
            item.setPlantConservation(null);
        }
        // Clear bidirectional one-to-many parent relationship with PhenologyRecord
        for (PhenologyRecord item : plantConservation.getPhenologyRecords()) {
            item.setPlantConservation(null);
        }
        // Clear bidirectional one-to-many parent relationship with Planting
        for (Planting item : plantConservation.getPlanting()) {
            item.setPlantConservation(null);
        }
        // Clear bidirectional one-to-many parent relationship with PropagationCultivation
        for (PropagationCultivation item : plantConservation.getPropagationCultivation()) {
            item.setPlantConservation(null);
        }
        getPlantConservationRepository().delete(plantConservation);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param entities
     * @return List
     */
    @Transactional
    public List<PlantConservation> save(Iterable<PlantConservation> entities) {
        return getPlantConservationRepository().save(entities);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param ids
     */
    @Transactional
    public void delete(Iterable<Long> ids) {
        List<PlantConservation> toDelete = getPlantConservationRepository().findAll(ids);
        getPlantConservationRepository().deleteInBatch(toDelete);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param entity
     * @return PlantConservation
     */
    @Transactional
    public PlantConservation save(PlantConservation entity) {
        return getPlantConservationRepository().save(entity);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param id
     * @return PlantConservation
     */
    public PlantConservation findOne(Long id) {
        return getPlantConservationRepository().findOne(id);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param id
     * @return PlantConservation
     */
    public PlantConservation findOneForUpdate(Long id) {
        return getPlantConservationRepository().findOneDetached(id);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param ids
     * @return List
     */
    public List<PlantConservation> findAll(Iterable<Long> ids) {
        return getPlantConservationRepository().findAll(ids);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return List
     */
    public List<PlantConservation> findAll() {
        return getPlantConservationRepository().findAll();
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return Long
     */
    public long count() {
        return getPlantConservationRepository().count();
    }

    @Override
    public Page<PlantConservation> search(Predicate predicate, Pageable pageable) {
        return getPlantConservationRepository().findAll(predicate, pageable);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param globalSearch
     * @param pageable
     * @return Page
     */
    public Page<PlantConservation> findAll(GlobalSearch globalSearch, Pageable pageable) {
        return getPlantConservationRepository().findAll(globalSearch, pageable, null);
    }

    @Override
    public Page<PlantConservation> findAll(GlobalSearch globalSearch, Pageable pageable, String creator) {
        return getPlantConservationRepository().findAll(globalSearch, pageable, creator);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @param ids
     * @param globalSearch
     * @param pageable
     * @return Page
     */
    public Page<PlantConservation> findAllByIdsIn(List<Long> ids, GlobalSearch globalSearch, Pageable pageable) {
        return getPlantConservationRepository().findAllByIdsIn(ids, globalSearch, pageable);
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return Class
     */
    public Class<PlantConservation> getEntityType() {
        return PlantConservation.class;
    }

    /**
     * TODO Auto-generated method documentation
     *
     * @return Class
     */
    public Class<Long> getIdType() {
        return Long.class;
    }
}
